#
# PVCSConfigFile.py
#
# this class covers the possible content of the PVCS config files
# Remarks: this class can't read or write a config file, this is only
#          the storage for the content. For read or write operations
#          use the classes PVCSConfigFileReader and PVCSConfigFileWriter
#
# Author: Uwe Stieber
# Copyright (c) 1998, 1999 TakeFive Software, Salzburg
#

# import some system modules
import UserDict
import UserList
import string
import re
import sys
import os

# import PVCS constants and helper functions
import PVCSConstants

# debug variable
import PVCSConstants

class PVCSConfigFile:
	# some class privates
	__validKeys = None			# list of used keys in the config file
								# use it for validation of the keys found
								# by PVCSConfigFileReader
								
	__ArchiveSuffixes = None	# dictionary of parsed archive
								# suffix rules
								
	__Diagnostic = 0			# PVCS diagnostic level
	__Quiet = 1					# PVCS message display
	__SignOn = 0				# PVCS copyright message
	
	def __init__(self):
		# constructor
		if PVCSConstants.TEST: print "(PVCS Config File)@B@g>>>@x __init__@B"
		
		# initialize the class variables
		self.__validKeys = UserList.UserList()
		self.__ArchiveSuffixes = UserDict.UserDict()
		self.__Diagnostic = 0
		self.__Quiet = 1
		self.__SignOn = 0
		
		# clear the content of the class variables
		# definite to null
		###__validKeys.clear()
		self.clearSuffixRules();

		# currently we accept following keys
		self.__validKeys.append(string.upper("ArchiveSuffix"))
		self.__validKeys.append(string.upper("Diagnostic"))
		self.__validKeys.append(string.upper("Quiet"))
		self.__validKeys.append(string.upper("Verbose"))
		self.__validKeys.append(string.upper("SignOn"))
		self.__validKeys.append(string.upper("NoSignOn"))

		if PVCSConstants.TEST: print "(PVCS Config File)@B@r<<<@x __init__@B"
		return
				
	def isValidKey(self, aKeyName):
		# method check's, if a key will be accepted by this class
		if PVCSConstants.TEST:
			print "(PVCS Config File)@B@g>>>@x isValidKey (aKeyName = '%s')@B" % aKeyName
			print "(PVCS Config File)\tList of valid Keys: @B@b",
			print self.__validKeys.data,
			print "@x@B"
		return string.upper(aKeyName) in self.__validKeys.data
			
	def addSuffixRule(self, aSuffix=None, aRule):
		# add a new suffix rule if the suffix doesn't already
		# exists, otherwise update the rule
		# Remark: the suffix is not a regular expression
		if PVCSConstants.TEST: print "(PVCS Config File)@B@g>>>@x addSuffixRule@B"
		if aSuffix is None:
			# the Rule is for all files
			aSuffix = '.?'
		if PVCSConstants.TEST: print "(PVCS Config File)\taSuffix = '@B@b%s@x@b'; aRule = '@B@b%s@x@b'" % (aSuffix, aRule)
		# check correct syntax
		if string.find(aSuffix, '?') != -1:
			# rule part must be divideable by two
			if len(aRule) % 2 != 0 and aRule[0] != '+':
				raise PVCSConstants.PVCSConfigFileSyntaxError
			else:
				self.__ArchiveSuffixes.data[aSuffix] = aRule
		else:
			self.__ArchiveSuffixes.data[aSuffix] = aRule
		if PVCSConstants.TEST: print "(PVCS Config File)@B@r<<<@x addSuffixRule@B"
		return
		
	def removeSuffixRule(self, aSuffix):
		if PVCSConstants.TEST: print "(PVCS Config File)@B@g>>>@x removeSuffixRule (aSuffix = '%s')@B" % aSuffix
		# remove a suffix rule from th list
		del self.__ArchiveSuffixes.data[aSuffix]
		if PVCSConstants.TEST: print "(PVCS Config File)@B@r<<<@x removeSuffixRule@B"
		return
		
	def getSuffixRule(self, aSuffix):
		# returns the rule for the given Suffix
		if PVCSConstants.TEST: print "(PVCS Config File)@B@g>>>@x getSuffixRule (aSuffix = '%s')@B" % aSuffix
		if PVCSConstants.TEST: print "(PVCS Config File)@B@r<<<@x getSuffixRule (aRule = '%s')@B" % self.__ArchiveSuffixes.get(aSuffix)
		return self.__ArchiveSuffixes.get(aSuffix)
			
	def findSuffixKey(self, fileSuffix):
		# try to find out, which suffix key from the current list
		# can be used
		if PVCSConstants.TEST: print "(PVCS Config File)@B@g>>>@x findSuffixKey (fileSuffix = '%s')@B" % fileSuffix
		if self.__ArchiveSuffixes.has_key(fileSuffix):
			# found direct association
			if PVCSConstants.TEST: print "(PVCS Config File)@B@r<<<@x findSuffixKey@B"
			return fileSuffix
		else:
			# try to find a meta rule
			matchedMetaSuffix = None
			for aSuffix in self.__ArchiveSuffixes.keys():
				# look through all rules which contains a meta character
				if string.find(aSuffix, '?') != -1 and aSuffix != '.?':
					# it's a meta rule
					# translate it to regular expression
					# Note: string.translate / string.maketrans is
					# not useable in this situation
					aRegExPattern = PVCSConstants.makeRegEx(aSuffix)
					# try to match (add IGNORECASE as flag for case insensitiv working on Windows)
					try:
						#print ">>> use regular expression: %s" % aRegExPattern
						flags = 0
						# disabled case insensitiv matching on windows as well,
						# because PVCS didn't do that
						#if sys.platform == "win32":
						#	# I ... IGNORECASE
						#	flags = re.I
						if re.match(aRegExPattern, fileSuffix, flags) != None:
							matchedMetaSuffix = aSuffix
							break
					except re.error:
						if PVCSConstants.TEST: print "(PVCS Config File)\tNot a regular expression: '%s'" % re.escape(aRegExPattern)
			if matchedMetaSuffix == None:
				# no matching suffix found, use finally
				# the suffix for all other files if this key exists
				if self.__ArchiveSuffixes.has_key('.?'):
					matchedMetaSuffix = '.?'
			# send back the matched Meta Suffix String
			if PVCSConstants.TEST: print "(PVCS Config File)@B@r<<<@x findSuffixKey@B"
			return matchedMetaSuffix

	def clearSuffixRules(self):
		# clear all suffix rules and add the PVCS default behavior
		# for all files (ArchivSuffix = ??v___)
		if PVCSConstants.TEST: print "(PVCS Config File)@B@g>>>@x clearSuffixRules@B"
		self.__ArchiveSuffixes.clear()
		self.addSuffixRule(aRule = '??v___')
		if PVCSConstants.TEST: print "(PVCS Config File)@B@r<<<@x clearSuffixRules@B"
		return

	def store(self, aSplittedLine):
		# PVCSConfigFileReader found a valid key and
		# sended us the content of the valid line splitted
		# into components inside a list. We have to do the
		# further analysing here.
		# ARCHIVESUFFIX directive ??
		if PVCSConstants.TEST: print "(PVCS Config File)@B@g>>>@x store@B"
		if string.upper(aSplittedLine[0]) == "ARCHIVESUFFIX":
			# ArchiveSuffix mode
			if len(aSplittedLine) == 2:
				# only the rule is given, is valid for all files
				self.addSuffixRule(aRule = aSplittedLine[1])
			else:
				# we should have exactly 3 items
				if len(aSplittedLine) == 3:
					# correct syntax
					self.addSuffixRule(aSplittedLine[1], aSplittedLine[2])
				else:
					# store it as single rules to the database
					for aSourceSuffix in range(1, len(aSplittedLine) - 1):
						self.addSuffixRule(aSplittedLine[aSourceSuffix], aSplittedLine[len(aSplittedLine) - 1])
		if string.upper(aSplittedLine[0]) == "DIAGNOSTIC":
			# Diagnostic level mode
			# we need at least two items
			if len(aSplittedLine) >= 2:
				self.setDiagnostic(int(aSplittedLine[1]))
		if string.upper(aSplittedLine[0]) == "QUIET":
			# set Quiet flag
			self.setQuiet(1)
		if string.upper(aSplittedLine[0]) == "VERBOSE":
			# clear the Quiet flag
			self.setQuiet(0)
		if string.upper(aSplittedLine[0]) == "SIGNON":
			# set the SignOn flag
			self.setSignOn(1)
		if string.upper(aSplittedLine[0]) == "NOSIGNON":
			# clear the SignOn flag
			self.setSignOn(0)
		# no further valid keys,
		# end of method reached
		if PVCSConstants.TEST: print "(PVCS Config File)@B@r<<<@x store@B"
		return
	
	def printArchiveSuffixList(self):
		# prints out the complete list of known
		# archive suffix rules
		if PVCSConstants.TEST: print "(PVCS Config File)@B@g>>>@x printArchiveSuffixList@B"
		print "Archive Suffix Rules:"
		for aSuffixKey in self.__ArchiveSuffixes.keys():
			print "%s\t =\t %s" % (aSuffixKey, self.getSuffixRule(aSuffixKey))
		print "<<< end of list"
		if PVCSConstants.TEST: print "(PVCS Config File)@B@r<<<@x printArchiveSuffixList@B"
		return
	
	def setDiagnostic(self, diagnosticLevel):
		# set the diagnostic level
		if PVCSConstants.TEST: print "(PVCS Config File)@B@g>>>@x setDiagnostic@B"
		self.__Diagnostic = diagnosticLevel
		if PVCSConstants.TEST: print "(PVCS Config File)@B@r<<<@x setDiagnostic@B"
		return

	def getDiagnostic(self):
		# returns the diagnostic level
		if PVCSConstants.TEST: print "(PVCS Config File)@B getDiagnostic@B"
		return self.__Diagnostic
		
	def setQuiet(self, Quiet):
		# set the quiet flag
		if PVCSConstants.TEST: print "(PVCS Config File)@B@g>>>@x setQuiet@B"
		self.__Quiet = Quiet
		if PVCSConstants.TEST: print "(PVCS Config File)@B@r<<<@x setQuiet@B"
		return

	def getQuiet(self):
		# returns the quiet flag
		if PVCSConstants.TEST: print "(PVCS Config File)@B getQuiet@B"
		return self.__Quiet
		
	def setSignOn(self, SignOn):
		# set the SignOn flag
		if PVCSConstants.TEST: print "(PVCS Config File)@B@g>>>@x setSignOn@B"
		self.__SignOn = SignOn
		if PVCSConstants.TEST: print "(PVCS Config File)@B@r<<<@x setSignOn@B"
		return

	def getSignOn(self):
		# returns the SignOn flag
		if PVCSConstants.TEST: print "(PVCS Config File)@B getSignOn@B"
		return self.__SignOn
		
	def getArchiveSuffixList(self):
		# returns the suffix rule dictionary
		if PVCSConstants.TEST: print "(PVCS Config File)@B getArchiveSuffixList@B"
		return self.__ArchiveSuffixes.data
		
	def calculateArchiveExtension(self, aFileExtension):
		# calculates the new archive suffix
		if PVCSConstants.TEST: print "(PVCS Config File)@B@g>>>@x calculateArchiveExtension (aFileExtension = '%s')@B" % aFileExtension
		aSuffixKey = self.findSuffixKey(aFileExtension)
		if aSuffixKey != None:
			# start calculating
			aSuffixRule = self.getSuffixRule(aSuffixKey)
			if aSuffixRule != None:
				if string.find(aSuffixRule, '?') != -1 and aSuffixRule[0] != '+':
					# suffix rule is a meta rule
					rule = aSuffixRule[:len(aSuffixRule)/2]
					replacements = aSuffixRule[len(aSuffixRule)/2:]
					newSuffix = ""
					if string.find(rule, '.') == -1 and string.find(aFileExtension, '.') != -1:
						aFileExtension = aFileExtension[1:]
					# walk over the extension
					for aCharIndex in range(len(rule)):
						if rule[aCharIndex] == '?':
							if aCharIndex >= len(aFileExtension):
								# append a character from replacements
								newSuffix = newSuffix + replacements[aCharIndex]
							else:
								newSuffix = newSuffix + aFileExtension[aCharIndex]
						else:
							# append the character from rule
							newSuffix = newSuffix + rule[aCharIndex]
					# check, if there is something behind the part
					# of the extension, which is effected by the rule
					if len(rule) < len(aFileExtension):
						newSuffix = newSuffix + aFileExtension[len(rule):]
					if PVCSConstants.TEST: print "(PVCS Config File)@B@r<<<@x calculateArchiveExtension (Extension = '%s')@B" % ('.' + newSuffix)
					return '.' + newSuffix
				else:
					# suffix rule is a direct replacement or an attachement
					if aSuffixRule[0] == '+':
						# append it
						if aFileExtension != '.':
							newExtension = aFileExtension + aSuffixRule[1:]
						else:
							newExtension = aSuffixRule[1:]
						if PVCSConstants.TEST: print "(PVCS Config File)@B@r<<<@x calculateArchiveExtension (Extension = '%s')@B" % newExtension
						return newExtension
					else:
						if PVCSConstants.TEST: print "(PVCS Config File)@B@r<<<@x calculateArchiveExtension (Extension = '%s')@B" % aSuffixRule
						return aSuffixRule
			else:
				raise PVCSConstants.PVCSNoSuffixRule
		else:
			raise PVCSConstants.PVCSNoSuffixRule
